﻿// -----------------------------------------------------------------------
// <copyright file="AzureStorage.cs">
// Copyright (c) 2013-2014 Andrey Veselov. All rights reserved.
// License:  Microsoft Public License (MS-PL)
// Contacts: http://andrey.moveax.com  andrey@moveax.com
// </copyright>
// -----------------------------------------------------------------------

namespace FileWarehouse.Azure
{
    using System;
    using System.Collections.Generic;
    using System.Diagnostics.Contracts;
    using System.Linq;
    using System.Threading.Tasks;
    using Microsoft.WindowsAzure;
    using Microsoft.WindowsAzure.Storage;
    using Microsoft.WindowsAzure.Storage.Blob;

    public class AzureStorage : IStorage
    {
        private readonly CloudBlobClient _blobClient;

        public AzureStorage(string connectionStringName)
        {
            Contract.Requires(!string.IsNullOrEmpty(connectionStringName));

            var storageAccount = CloudStorageAccount.Parse(CloudConfigurationManager.GetSetting(connectionStringName));
            this._blobClient = storageAccount.CreateCloudBlobClient();
        }

        public Task<IEnumerable<string>> GetContainersListAsync(string mask)
        {
            var tcs = new TaskCompletionSource<IEnumerable<string>>();

            Task.Run(() => {
                try {
                    var containers = this._blobClient.ListContainers(mask)
                        .Select(c => c.Name)
                        .ToList();

                    tcs.SetResult(containers);
                }
                catch (Exception e) {
                    tcs.SetException(
                        new FileWarehouse.StorageException(
                            StorageExceptionReason.StorageOperationFailed,
                            string.Format("Unable to get the containers list. Mask: {0}", mask),
                            e));
                }
            });

            return tcs.Task;
        }

        public async Task<IStorageContainer> CreateOrGetContainerAsync(string name, ContainerPermission permission, bool failIfExist)
        {
            CloudBlobContainer container = this._blobClient.GetContainerReference(name.ToLower());
            var isCreated = await container.CreateIfNotExistsAsync().ConfigureAwait(false);

            if (failIfExist && !isCreated)
                throw new FileWarehouse.StorageException(
                    StorageExceptionReason.ContainerExistAlready, "Container exist already.");

            IStorageContainer storageContainer = new AzureStorageContainer(container);
            await storageContainer.SetPermissionAsync(permission).ConfigureAwait(false);

            return storageContainer;
        }

        public async Task<IStorageContainer> GetContainerAsync(string name)
        {
            CloudBlobContainer container = this._blobClient.GetContainerReference(name.ToLower());

            bool containerExists = await container.ExistsAsync().ConfigureAwait(false);
            if (!containerExists)
                throw new FileWarehouse.StorageException(
                    StorageExceptionReason.ContainerNotFound,
                    string.Format("Container '{0}' not exist.", name));

            IStorageContainer storageContainer = new AzureStorageContainer(container);

            return storageContainer;
        }

        public async Task DeleteContainerAsync(string name)
        {
            CloudBlobContainer container = this._blobClient.GetContainerReference(name.ToLower());
            await container.DeleteIfExistsAsync().ConfigureAwait(false);
        }
    }
}